for (int i = 1, k = 0; i <= n; i++) { if (rk[i] == 1) k = 0; else { if (k > 0) k--; int j = sa[rk[i] - 1]; while (i + k <= n && j + k <= n && s[i - 1 + k] == s[j - 1 + k]) k++; } height[rk[i]] = k; }
LCP问题
height[]数组只是计算出了相邻两个后缀子串地公共前缀。而当我们想要计算任意两个后缀字串的LCP(Longest Common Prefix)时该怎么办呢?这时候其实也需要利用height[]数组。
int buc[MAXN]; int sa[MAXN]; int rk[MAXN], tmp[MAXN]; int first[MAXN], second[MAXN]; string s;
inttrans(char c) { if (c>='0' && c<='9') return c - '0' + 1; if (c>='A' && c<='Z') return c - 'A' + 11; if (c>='a' && c<='z') return c - 'a' + 37; return0; }
intmain() { ios::sync_with_stdio(false);
string s; cin >> s;
int n = s.length();
for (int i = 1; i<=n; i++) buc[ trans(s[i-1]) ] ++; for (int i = 1; i<=MAXM; i++) buc[i] += buc[i-1];
for (int i = 1; i<=n; i++) rk[i] = buc[ trans(s[i-1]) - 1 ] + 1;
for (int t = 1; t<n; t *= 2) { for (int i = 1; i<=n; i++) { first[i] = rk[i]; second[i] = i+t>n? 0: rk[i+t]; }
fill(buc, buc+n+1, 0); for (int i = 1; i<=n; i++) buc[ second[i] ] ++; for (int i = 1; i<=n; i++) buc[i] += buc[i-1]; for (int i = 1; i<=n; i++) tmp[ n - --buc[ second[i] ] ] = i;
fill(buc, buc+n+1, 0); for (int i = 1; i<=n; i++) buc[ first[i] ] ++; for (int i = 1; i<=n; i++) buc[i] += buc[i-1]; for (int i = 1; i<=n; i++) { int j = tmp[i]; sa[ buc[first[j]]-- ] = j; }
//不加这个优化就会TLE bool flag = true; int k = 0; for (int i = 1; i<=n; i++) { int j = sa[i];
for (int i = 1, k = 0; i <= n; i++) { if (rk[i] == 1) k = 0; else { if (k > 0) k--; int j = sa[rk[i] - 1]; while (i + k <= n && j + k <= n && s[i - 1 + k] == s[j - 1 + k]) k++; } height[rk[i]] = k; }
int ans = 0; for (int i = 1; i<=n; i++) if((sa[rk[i]]>slen&&sa[rk[i]-1]<slen)||(sa[rk[i]]<slen&&sa[rk[i]-1]>slen)) ans=max(ans,height[rk[i]]);